package com.szxx.mahjong.qianjiang.mahjong;

import com.szxx.constant.GameConstant;
import com.szxx.domain.CardDown;
import com.szxx.domain.GameTable;
import com.szxx.domain.MahjongCheckResult;
import com.szxx.domain.Player;
import com.szxx.mahjong.qianjiang.constans.GameRule;
import com.szxx.mahjong.qianjiang.domain.TingCheckResult;
import com.szxx.processor.mahjong.MahjongProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Component
public class QianjiangMahjongProcessor extends MahjongProcessor {

    private Logger logger = LoggerFactory.getLogger(QianjiangMahjongProcessor.class);

    public QianjiangMahjongProcessor() {
    }

    @Override
    public MahjongCheckResult checkGang(GameTable gt, byte newCard, Player pl, boolean isMyCard) {
        byte pizi = gt.getRiffraffCard();
        byte laizi = gt.getLazarailloCard();

        MahjongCheckResult res = new MahjongCheckResult();

        res.targetCard = newCard;
        res.pengCardValue = 0;
        res.playerTableIndex = pl.getTablePos();

        List<Byte> handList = new ArrayList<Byte>();
        for (int i = 0; i < pl.getCardsInHand().size(); i++) {
            byte b = pl.getCardsInHand().get(i);
            if (handList.contains(b))
                continue;

            handList.add(b);
        }

        if (isMyCard) {
            if (newCard > 0) {
                //刚摸进来的牌也要检测
                if (!handList.contains(newCard)) {
                    handList.add(newCard);
                }
            }
        }

        List<CardDown> cardGangs = res.gangList;
        if (isMyCard) {
            for (int k = 0; k < handList.size(); k++) {
                byte gg = handList.get(k);
                int num = pl.getXCardNumInHand(gg);
                if (gg == laizi) {
                    continue;
                }

                if (gg == newCard) {
                    num++;
                }

                if (num == 4) {
                    CardDown cardown = new CardDown();
                    cardown.type = GameConstant.MAHJONG_OPERTAION_AN_GANG;
                    cardown.cardValue = (gg << 24) | (gg << 16) | (gg << 8) | gg;
                    cardGangs.add(cardown);
                } else if (num == 1) {
                    //潜江麻将,摸了牌之后才能补杠，其他时间不能补杠
                    if (pl.hasPeng(gg) && gg == newCard) {
                        CardDown bucardown = new CardDown();
                        bucardown.type = GameConstant.MAHJONG_OPERTAION_BU_GANG;
                        bucardown.cardValue = (gg << 24) | (gg << 16) | (gg << 8) | gg;
                        cardGangs.add(bucardown);
                    }
                }
                if (num == 3 && gg == pizi) {
                    //潜江玩法，如果3个痞子可以亮牌,亮牌加入到杠中一起提示
                    CardDown liangpai = new CardDown();
                    liangpai.type = GameConstant.MAHJONG_OPERTAION_AN_GANG;
                    liangpai.cardValue = (pizi << 16) | (pizi << 8) | pizi;
                    cardGangs.add(liangpai);
                }
            }

            //癞子杠不显示到杠列表
//            byte gg = laizi;
//            if (pl.getXCardNumInHand(gg) > 0 || card == gg) {
//                CardDown cardown = new CardDown();
//                cardown.type = GameConstant.MAHJONG_OPERTAION_LAIZI_GANG;
//                cardown.cardValue = (gg << 24) | (gg << 16) | (gg << 8) | gg;
//                cardGangs.add(cardown);
//            }
        } else {
            int num = pl.getXCardNumInHand(newCard);
            if (num == 3) {
                CardDown cardown = new CardDown();
                cardown.type = GameConstant.MAHJONG_OPERTAION_MING_GANG;
                cardown.cardValue = (newCard << 16) | (newCard << 8) | newCard;
                cardGangs.add(cardown);
            }
            //潜江玩法，如果3个痞子可以亮牌,亮牌加入到杠中一起提示
            int piziNum = pl.getXCardNumInHand(pizi);
            if (piziNum == 2 && pizi == newCard) {
                CardDown liangpai = new CardDown();
                liangpai.type = GameConstant.MAHJONG_OPERTAION_MING_GANG;
                liangpai.cardValue = (pizi << 16) | (pizi << 8) | pizi;
                cardGangs.add(liangpai);
            }
        }

        if (cardGangs.size() > 0) {
            res.opertaion = GameConstant.MAHJONG_OPERTAION_GANG;
            return res;
        }

        return null;
    }

    @Override
    protected MahjongCheckResult doCheckWin(byte newCard, Player pl, GameTable gt) {
        //byte pizi = gt.getBaoCard();
        byte laizi = gt.getLazarailloCard();
        int laziNum = 0;
        //card是别人出的牌:硬胡(癞子归位、无癞子、做将不算归位)才允许点炮
        if (pl.getCardGrab() == 0) {
            //别人出牌，硬胡才能胡牌。癞子归位算硬胡，做将不算归位
            if (newCard == laizi) {//别人打出癞子不能胡牌
                return null;
            }
            laziNum = pl.getXCardNumInHand(laizi);//获取玩家手上的癞子数
            //硬胡在real_check_hu判断
        } else {//card是自己抓的牌
            pl.addCardInHand(newCard);
            laziNum = pl.getXCardNumInHand(laizi);//获取玩家手上的癞子数,摸上来的牌也要算
            pl.removeCardInHand(newCard);
        }

        //潜江麻将:【规则细分a:全新规则】最多只允许有一个癞子的时候自摸和点炮（归位也算有一个癞子）,超过一个癞子不能胡
        if ((GameRule.GAME_PLAY_RULE_QIANJIANG_QUANXIN & gt.getVipRule()) != 0 && laziNum > 1) {
            return null;
        }

        MahjongCheckResult result = realCheckHu(newCard, pl, gt);

        if (result == null) {
            return null;
        }

        //潜江麻将:【规则细分b	:一赖到底】一赖到底最多只允许有一个癞子，归位才可以胡牌，未归位的时候不允许胡牌
        if ((GameRule.GAME_PLAY_RULE_QIANJIANG_YILAIDAODI & gt.getVipRule()) != 0) {
            //一癞到底子玩法，没有癞子
            if ((GameRule.GAME_PLAY_RULE_QIANJIANG_WULAI & gt.getVipRule()) != 0) {
                //有癞子不能胡
                if (laziNum > 0) {
                    return null;
                }
            }
            //癞子个数大于1不能胡
            if (laziNum > 1) {
                return null;
                //癞子未归位不能胡
            } else if (result != null && (result.fanResult & GameRule.MAHJONG_HU_CODE_YOU_LAI_ZI) != 0) {
                return null;
            }
        }
        //潜江麻将:【规则细分c:全胡】可以多个癞子，能胡牌就行，癞子归位算硬胡,杠牌为基础得分
        return result;
    }

    private MahjongCheckResult realCheckHu(byte newCard, Player pl, GameTable gt) {
        // 把牌先放手里，有序,后面再删掉
        if (newCard != 0) {
            pl.addCardInHand(newCard);
        }

        MahjongCheckResult huresult = new MahjongCheckResult();
        huresult.opertaion = GameConstant.MAHJONG_OPERTAION_HU;
        huresult.playerTableIndex = pl.getTablePos();
        huresult.targetCard = newCard;

        byte hun_cd = gt.getLazarailloCard();
        boolean iszimo = (pl.getCardGrab() != 0);
        List<Byte> c1 = pl.getCardsInHand();

        do {
            TingCheckResult wan = new TingCheckResult();
            TingCheckResult tiao = new TingCheckResult();
            TingCheckResult tong = new TingCheckResult();
            TingCheckResult zi = new TingCheckResult();
            //返回用剩下的混牌数
            int hun_num = check_wan_tiao_tong_hu(hun_cd, pl, c1, wan, tiao, tong, zi);
            if (hun_num == -100)
                break;
            int cheng_pai_num = 0;
            if (wan.result == GameConstant.MAHJONG_TING_CODE_CHENG_PAI)
                cheng_pai_num++;
            if (tiao.result == GameConstant.MAHJONG_TING_CODE_CHENG_PAI)
                cheng_pai_num++;
            if (tong.result == GameConstant.MAHJONG_TING_CODE_CHENG_PAI)
                cheng_pai_num++;
            if (zi.result == GameConstant.MAHJONG_TING_CODE_CHENG_PAI)
                cheng_pai_num++;

            //
            //int dui_zi=0;
            int duizi_num = 0;
            if (wan.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                duizi_num++;
                //dui_zi=wan.duiZi;
            }
            if (tiao.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                duizi_num++;
                //dui_zi=tiao.duiZi;
            }
            if (tong.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                duizi_num++;
                //dui_zi=tong.duiZi;
            }
            if (zi.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                duizi_num++;
            }

            //有太多对子，如果还有混牌，其中一对变刻子，
            while (duizi_num > 1 && hun_num > 0) {
                if (zi.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                    duizi_num--;
                    cheng_pai_num++;
                    hun_num--;
                    zi.duiZi = 0;
                    zi.keziNum++;
                    zi.hunUsed++;

                    continue;
                }

                if (wan.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                    duizi_num--;
                    cheng_pai_num++;
                    hun_num--;

                    wan.duiZi = 0;
                    wan.keziNum++;
                    wan.hunUsed++;
                    continue;
                }
                if (tong.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                    duizi_num--;
                    cheng_pai_num++;
                    hun_num--;

                    tong.duiZi = 0;
                    tong.keziNum++;
                    tong.hunUsed++;
                    continue;
                }
                if (tiao.result == GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI) {
                    duizi_num--;
                    cheng_pai_num++;
                    hun_num--;

                    tiao.duiZi = 0;
                    tiao.keziNum++;
                    tiao.hunUsed++;
                    continue;
                }
            }

            int total_num = wan.keziNum + tiao.keziNum + tong.keziNum;
            //2张胡别人不算一坎
            if (pl.getXCardNumInHand(newCard) == 3) {
                wan.removeKe(newCard);
                tiao.removeKe(newCard);
                tong.removeKe(newCard);
            }
            int kezi = wan.keziNum + tiao.keziNum + tong.keziNum;
            if (cheng_pai_num >= 3 && duizi_num == 1) {
                int vip_rule = gt.getVipRule();
                int youlaizi = 0;
                int value = 0;
                int laiziNum = pl.getXCardNumInHand(hun_cd);
                if ((wan.hunUsed > 0 || wan.useHuncardAsNormalNum > 0) && ((hun_cd & 0xf0) == 0x0)) {
                    value = wan.getXiaojiShunziNum(hun_cd, vip_rule);
                }
                if ((tiao.hunUsed > 0 || tiao.useHuncardAsNormalNum > 0) && ((hun_cd & 0xf0) == 0x10)) {
                    value = tiao.getXiaojiShunziNum(hun_cd, vip_rule);
                }
                if ((tong.hunUsed > 0 || tong.useHuncardAsNormalNum > 0) && ((hun_cd & 0xf0) == 0x20)) {
                    value = tong.getXiaojiShunziNum(hun_cd, vip_rule);
                }

                boolean hasHunDuizi = false;
                boolean hasHunKezi = false;
                if (wan.find_dui_zi(hun_cd) || tiao.find_dui_zi(hun_cd) || tong.find_dui_zi(hun_cd) || zi.find_dui_zi(hun_cd)) {
                    hasHunDuizi = true;
                }
                if (wan.find_ke_zi(hun_cd) || tiao.find_ke_zi(hun_cd) || tong.find_ke_zi(hun_cd) || zi.find_ke_zi(hun_cd)) {
                    hasHunKezi = true;
                }

                int laizileft = 0;
                if (hasHunDuizi) {
                    laizileft = laiziNum - 2 - value;
                } else if (hasHunKezi) {
                    laizileft = laiziNum - 3 - value;
                } else {
                    laizileft = laiziNum - value;
                }

                int hunUsed = wan.hunUsed + tiao.hunUsed + tong.hunUsed;
                if (pl.getCardGrab() == 0) {
                    //点炮
                    if (hunUsed >= 1 || hasHunDuizi || hasHunKezi) {//硬胡才允许点炮
                        //hunUsed >= 1表示不是硬胡,hasHunDuizi
                        pl.removeCardInHand(newCard);
                        return null;
                    }
                } else {
                    //自摸
                    if (hunUsed == 0 && !hasHunDuizi) {//硬胡才允许点炮
                        huresult.addFanResult(GameRule.MAHJONG_HU_CODE_HEIMO);
                    }
                }

                if (hasHunDuizi) {
                    youlaizi = GameRule.MAHJONG_HU_CODE_YOU_LAI_ZI;
                }

                if (laizileft > 0) {
                    youlaizi = GameRule.MAHJONG_HU_CODE_YOU_LAI_ZI;
                }

                if (zi.hunUsed > 0) {
                    youlaizi = GameRule.MAHJONG_HU_CODE_YOU_LAI_ZI;
                }

                huresult.keZiNum = kezi;
                huresult.totalKeZiNum = total_num;
                //huresult.hasjiang = true;
                //双铺子：两个一样的顺，如345万 345万
                huresult.same2Shunzi = wan.hasTwoSameShunzi() + tiao.hasTwoSameShunzi() + tong.hasTwoSameShunzi();
                huresult.addFanResult(youlaizi);
                wan.clear_all();
                tiao.clear_all();
                tong.clear_all();
                pl.removeCardInHand(newCard);
                return huresult;
            } else {
                if (duizi_num > 1) {
                    //碰碰胡放到大三元和小三元后面计算
//                    MahjongCheckResult ppdui = check_hu_peng_peng_with_hun(card, pl, gt, hun_cd);
//                    if (ppdui != null) {
//                        check_qingyseorhun(card, pl, ppdui, hun_cd);
//                        check_jiangyise(card, pl, ppdui, hun_cd);
//
//                        pl.removeCardInHand(card);
//                        return ppdui;
//                    }
                }
            }
            wan.clear_all();
            tiao.clear_all();
            tong.clear_all();
            //
        } while (false);
        // 临时牌，先移掉
        pl.removeCardInHand(newCard);
        return null;
    }

    protected int check_wan_tiao_tong_hu(byte hun_cd, Player pl, List<Byte> c1
            , TingCheckResult wan, TingCheckResult tiao, TingCheckResult tong, TingCheckResult zi) {
        int hun_num = pl.getXCardNumInHand(hun_cd);
        int total_hun_num = hun_num;
        byte hun2 = 0;
        boolean bRes = false;
        if ((hun_cd & GameConstant.MAHJONG_CODE_COLOR_MASK) == GameConstant.MAHJONG_CODE_COLOR_WAN) {
            for (int i = total_hun_num; i >= 0; --i) {
                wan.reset();
                tiao.reset();
                tong.reset();
                zi.reset();
                hun_num = pl.getXCardNumInHand(hun_cd);
                bRes = hu_check_with_hun(c1, GameConstant.MAHJONG_CODE_COLOR_WAN, hun_cd, hun_num, i, wan);
                if (bRes) {
                    hun_num -= wan.useHuncardAsNormalNum;
                    hun_num -= wan.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_TIAO, hun_cd, hun2, hun_num, tiao);
                    if (!bRes)
                        continue;// 当前条子听不了
                    hun_num -= tiao.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_TONG, hun_cd, hun2, hun_num, tong);
                    if (!bRes)
                        continue;// 当前筒子听不了
                    hun_num -= tong.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_ZI, hun_cd, hun2, hun_num, zi);
                    if (!bRes)
                        continue;// 字牌听不了
                    hun_num -= zi.hunUsed;
                    return hun_num;
                }
            }
        } else if ((hun_cd & GameConstant.MAHJONG_CODE_COLOR_MASK) == GameConstant.MAHJONG_CODE_COLOR_TONG) {
            for (int i = total_hun_num; i >= 0; --i) {
                wan.reset();
                tiao.reset();
                tong.reset();
                zi.reset();
                hun_num = pl.getXCardNumInHand(hun_cd);
                bRes = hu_check_with_hun(c1, GameConstant.MAHJONG_CODE_COLOR_TONG, hun_cd, hun_num, i, tong);
                if (bRes) {
                    hun_num -= tong.useHuncardAsNormalNum;
                    hun_num -= tong.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_TIAO, hun_cd, hun2, hun_num, tiao);
                    if (!bRes)
                        continue;// 当前条子听不了
                    hun_num -= tiao.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_WAN, hun_cd, hun2, hun_num, wan);
                    if (!bRes)
                        continue;// 当前筒子听不了
                    hun_num -= wan.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_ZI, hun_cd, hun2, hun_num, zi);
                    if (!bRes)
                        continue;// 字牌听不了
                    hun_num -= zi.hunUsed;
                    return hun_num;
                }
            }
        } else if ((hun_cd & GameConstant.MAHJONG_CODE_COLOR_MASK) == GameConstant.MAHJONG_CODE_COLOR_TIAO) {
            for (int i = total_hun_num; i >= 0; --i) {
                wan.reset();
                tiao.reset();
                tong.reset();
                zi.reset();
                hun_num = pl.getXCardNumInHand(hun_cd);
                bRes = hu_check_with_hun(c1, GameConstant.MAHJONG_CODE_COLOR_TIAO, hun_cd, hun_num, i, tiao);
                if (bRes) {
                    hun_num -= tiao.useHuncardAsNormalNum;
                    hun_num -= tiao.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_WAN, hun_cd, hun2, hun_num, wan);
                    if (!bRes)
                        continue;// 当前条子听不了
                    hun_num -= wan.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_TONG, hun_cd, hun2, hun_num, tong);
                    if (!bRes)
                        continue;// 当前筒子听不了
                    hun_num -= tong.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_ZI, hun_cd, hun2, hun_num, zi);
                    if (!bRes)
                        continue;// 字牌听不了
                    hun_num -= zi.hunUsed;
                    return hun_num;
                }
            }
        } else if ((hun_cd & GameConstant.MAHJONG_CODE_COLOR_MASK) == GameConstant.MAHJONG_CODE_COLOR_ZI) {
            for (int i = total_hun_num; i >= 0; --i) {
                wan.reset();
                tiao.reset();
                tong.reset();
                zi.reset();
                hun_num = pl.getXCardNumInHand(hun_cd);
                bRes = hu_check_with_hun(c1, GameConstant.MAHJONG_CODE_COLOR_ZI, hun_cd, hun_num, i, zi);
                if (bRes) {
                    hun_num -= zi.useHuncardAsNormalNum;
                    hun_num -= zi.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_WAN, hun_cd, hun2, hun_num, wan);
                    if (!bRes)
                        continue;// 当前条子听不了
                    hun_num -= wan.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_TONG, hun_cd, hun2, hun_num, tong);
                    if (!bRes)
                        continue;// 当前筒子听不了
                    hun_num -= tong.hunUsed;

                    bRes = hu_check_cycle(c1, GameConstant.MAHJONG_CODE_COLOR_TIAO, hun_cd, hun2, hun_num, tiao);
                    if (!bRes)
                        continue;// 字牌听不了
                    hun_num -= tiao.hunUsed;
                    return hun_num;
                }
            }
        }

        return -100;
    }

    private boolean hu_check_cycle(List<Byte> c1, int color, byte hun_cd, byte bao, int hun_num, TingCheckResult cc) {
        cc.unchecked = getCardsByColorWithoutHun(c1, color, hun_cd, bao);
        for (int j = 0; j < cc.unchecked.size(); ++j) {
            Byte value = cc.unchecked.get(j);
            if ((value & 0x0f) == 0x02) {
                cc.jiang2Num++;
            } else if ((value & 0x0f) == 0x05) {
                cc.jiang5Num++;
            } else if ((value & 0x0f) == 0x08) {
                cc.jiang8Num++;
            }
        }
        for (int i = 0; i <= hun_num; i++) {
            if (hu_check(cc, i)) {
                if (cc.find_dui_zi(color | 0x02) || cc.find_dui_zi(color | 0x05) || cc.find_dui_zi(color | 0x08)) {
                    cc.has258jiang = true;
                }
                if (!cc.has258jiang) {
                    cc.has258jiang = hasjiang(cc, cc.jiang2Num, color | 0x02);
                }
                if (!cc.has258jiang) {
                    cc.has258jiang = hasjiang(cc, cc.jiang5Num, color | 0x05);
                }
                if (!cc.has258jiang) {
                    cc.has258jiang = hasjiang(cc, cc.jiang8Num, color | 0x08);
                }
                return true;
            }
        }

        return false;
    }


    private boolean hu_check_with_hun(List<Byte> c1, int color, byte hun_cd, int hun_num, int use_hun_num, TingCheckResult cc) {
        if (use_hun_num > hun_num) {
            return false;
        }

        cc.unchecked = getCardsByColorWithHun(c1, color, hun_cd, use_hun_num);
        for (int j = 0; j < cc.unchecked.size(); ++j) {
            Byte value = cc.unchecked.get(j);
            if ((value & 0x0f) == 0x02) {
                cc.jiang2Num++;
            } else if ((value & 0x0f) == 0x05) {
                cc.jiang5Num++;
            } else if ((value & 0x0f) == 0x08) {
                cc.jiang8Num++;
            }
        }

        int hun_left = hun_num - use_hun_num;
        for (int i = 0; i <= hun_left; ++i) {
            if (hu_check(cc, i)) {
                cc.useHuncardAsNormalNum = use_hun_num;
                if (cc.find_dui_zi(color | 0x02) || cc.find_dui_zi(color | 0x05) || cc.find_dui_zi(color | 0x08)) {
                    cc.has258jiang = true;
                }
                if (!cc.has258jiang) {
                    cc.has258jiang = hasjiang(cc, cc.jiang2Num, color | 0x02);
                }
                if (!cc.has258jiang) {
                    cc.has258jiang = hasjiang(cc, cc.jiang5Num, color | 0x05);
                }
                if (!cc.has258jiang) {
                    cc.has258jiang = hasjiang(cc, cc.jiang8Num, color | 0x08);
                }
                return true;
            }
        }

        return false;
    }

    private boolean hu_check(TingCheckResult ck, int hunNum) {
        if (ck.unchecked.size() == 0) {
            if (ck.duiZi == 0 && ck.danDiao == 0 && ck.shunZi == 0)// 如果之前没有听牌，说明已经成牌
            {
                ck.result = GameConstant.MAHJONG_TING_CODE_CHENG_PAI;
                return true;
            } else if (ck.getDuiziNum() == 1) {
                ck.result = GameConstant.MAHJONG_TING_CODE_ONE_DUI_ZI;
                return true;
            }

            return false;
        }
        //
        byte b1 = ck.unchecked.get(0);
        //剩一张，用2张混子，组成一个刻子
        if (ck.unchecked.size() == 1) {
            //拿混子当对子
            if (hunNum > 0 && ck.getDuiziNum() == 0) {
                TingCheckResult ckx = new TingCheckResult();
                ckx.copy(ck);
                ckx.unchecked.remove(0);
                ckx.addDuizi(b1);

                ckx.hunUsed += 1;
                if (hu_check(ckx, hunNum - 1)) {
                    ck.result = ckx.result;
                    ck.copy(ckx);
                    return true;
                }
            }

            if (hunNum >= 2) {
                TingCheckResult ckx = new TingCheckResult();
                ckx.copy(ck);
                // 加多一个刻子
                ckx.keziNum++;
                ckx.unchecked.remove(0);
                int cc = b1 | (b1 << 8) | (b1 << 16);
                ckx.checked.add(cc);
                ckx.hunUsed += 2;
                if (hu_check(ckx, hunNum - 2)) {
                    ck.result = ckx.result;
                    ck.copy(ckx);
                    return true;
                }
            }
            return false;
        }
        byte b2 = ck.unchecked.get(1);

        //字牌不能做顺子
        boolean is_zi = false;
        int color1 = b1 & GameConstant.MAHJONG_CODE_COLOR_MASK;
        if (color1 == GameConstant.MAHJONG_CODE_COLOR_ZI)
            is_zi = true;

//		boolean is_tiao = false;
//		int color2=b1&GameConstant.MAHJONG_CODE_COLOR_MASK;
//		if(color2==GameConstant.MAHJONG_CODE_COLOR_TIAO)
//			is_tiao=true;
//
        //

        // 第一张作为对子,只能有一个对子
        if (b1 == b2 && ck.getDuiziNum() == 0) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            //
            ckx.unchecked.remove(0);
            ckx.unchecked.remove(0);
            //
            ckx.addDuizi(b1);
            //
            if (hu_check(ckx, hunNum)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }

        }
        //拿混子当对子,手里只有2张牌的情况
        if (hunNum > 0 && ck.getDuiziNum() == 0 && ck.unchecked.size() == 2) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            ckx.unchecked.remove(0);
            ckx.addDuizi(b1);
            ckx.hunUsed += 1;
            if (hu_check(ckx, hunNum - 1)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        if (ck.unchecked.size() < 3) {
            if (hunNum == 0)
                return false;
            //
            if (b1 == b2 - 1 || b1 == b2 - 2) {
                if (!is_zi) {
                    TingCheckResult ckx = new TingCheckResult();
                    ckx.copy(ck);
                    ckx.shunZiNum++;
                    ckx.unchecked.remove(0);
                    ckx.unchecked.remove(0);
                    int cc = 0;
                    if (b1 == b2 - 2) {
                        cc = b1 | ((b1 + 1) << 8) | ((b2) << 16);
                    } else if (b1 > 1) {
                        cc = (b1 - 1) | ((b1) << 8) | ((b2) << 16);
                    } else {
                        cc = b1 | ((b2) << 8) | ((b1 + 2) << 16);

                        //(b1-1) 是小鸡
                        if (b1 == 0x12) {
                            ckx.hunisxiaoji = true;
                        }
                    }
                    ckx.checked.add(cc);
                    ckx.hunUsed += 1;
                    if (hu_check(ckx, hunNum - 1)) {
                        ck.result = ckx.result;
                        ck.copy(ckx);
                        return true;
                    }
                }
            }
            // 第一张作为刻牌aaa,成牌
            if (b1 == b2) {
                TingCheckResult ckx = new TingCheckResult();
                ckx.copy(ck);
                // 加多一个刻子
                ckx.keziNum++;
                ckx.unchecked.remove(0);
                ckx.unchecked.remove(0);
                int cc = b1 | (b1 << 8) | (b1 << 16);
                ckx.checked.add(cc);
                ckx.hunUsed += 1;
                if (hu_check(ckx, hunNum)) {
                    ck.result = ckx.result;
                    ck.copy(ckx);
                    return true;
                }
            }
            return false;
        }
        byte b3 = ck.unchecked.get(2);
        // 第一张作为刻牌aaa,成牌
        if (b1 == b2 && b2 == b3) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            // 加多一个刻子
            ckx.keziNum++;
            ckx.unchecked.remove(0);
            ckx.unchecked.remove(0);
            ckx.unchecked.remove(0);
            int cc = b1 | (b1 << 8) | (b1 << 16);
            ckx.checked.add(cc);
            if (hu_check(ckx, hunNum)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        // 第一张作为顺牌abc，成牌
        if (is_zi == false && ck.foundCard((byte) (b1 + 1)) && ck.foundCard((byte) (b1 + 2))) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            ckx.shunZiNum++;
            ckx.unchecked.remove(0);
            ckx.remove((byte) (b1 + 1));
            ckx.remove((byte) (b1 + 2));
            //
            int cc = b1 | ((b1 + 1) << 8) | ((b1 + 2) << 16);
            ckx.checked.add(cc);
            //
            if (hu_check(ckx, hunNum)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        //////////////////////////////////////////////////////////////////////////////////
        //拿混子当对子
        if (hunNum > 0 && ck.getDuiziNum() == 0) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            ckx.unchecked.remove(0);
            ckx.addDuizi(b1);
            ckx.hunUsed += 1;
            if (hu_check(ckx, hunNum - 1)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        //用一张混子做刻子
        if (hunNum > 0 && b1 == b2) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            // 加多一个刻子
            ckx.keziNum++;
            ckx.unchecked.remove(0);
            ckx.unchecked.remove(0);
            int cc = b1 | (b1 << 8) | (b1 << 16);
            ckx.checked.add(cc);
            ckx.hunUsed += 1;
            if (hu_check(ckx, hunNum - 1)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }

        }
        //用一张混子做刻子
        if (hunNum > 0 && b1 == b3 && b2 != b3) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            // 加多一个刻子
            ckx.keziNum++;
            ckx.unchecked.remove(0);
            ckx.unchecked.remove(1);
            int cc = b1 | (b1 << 8) | (b1 << 16);
            ckx.checked.add(cc);
            ckx.hunUsed += 1;
            if (hu_check(ckx, hunNum - 1)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        // 第一张作为顺牌abc，成牌
        if (hunNum > 0 && is_zi == false && ck.foundCard((byte) (b1 + 2))) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            ckx.shunZiNum++;
            ckx.unchecked.remove(0);
            ckx.remove((byte) (b1 + 2));
            int cc = b1 | ((b1 + 1) << 8) | ((b1 + 2) << 16);
            ckx.checked.add(cc);
            ckx.hunUsed += 1;
            if (hu_check(ckx, hunNum - 1)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        // 第一张作为顺牌abc，成牌
        if (hunNum > 0 && is_zi == false && ck.foundCard((byte) (b1 + 1))) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            ckx.shunZiNum++;
            ckx.unchecked.remove(0);
            ckx.remove((byte) (b1 + 1));
            int cc = b1 | ((b1 + 1) << 8) | ((b1 + 2) << 16);
            ckx.checked.add(cc);
            ckx.hunUsed += 1;
            if (hu_check(ckx, hunNum - 1)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        //用2张混子做刻子
        if (hunNum >= 2) {
            TingCheckResult ckx = new TingCheckResult();
            ckx.copy(ck);
            // 加多一个刻子
            ckx.keziNum++;
            ckx.unchecked.remove(0);
            int cc = b1 | (b1 << 8) | (b1 << 16);
            ckx.checked.add(cc);
            ckx.hunUsed += 2;
            if (hu_check(ckx, hunNum - 2)) {
                ck.result = ckx.result;
                ck.copy(ckx);
                return true;
            }
        }
        return false;
    }


    private boolean hasjiang(TingCheckResult cc, int jiangNum, int value) {
        if (jiangNum == 2 && cc.find_ke_zi(value)) {
            return true;
        } else if (jiangNum == 3 && cc.find_ke_zi(value) && cc.getSpecifiedShunziNum(value) == 1) {
            return true;
        } else if (jiangNum == 4 && cc.find_ke_zi(value) && cc.getSpecifiedShunziNum(value) == 2) {
            return true;
        }

        return false;
    }

    private List<Byte> getCardsByColorWithHun(List<Byte> tl, int cc, byte hun_cd, int use_hun_num) {
        List<Byte> cs = new ArrayList<Byte>();
        int addHunNum = 0;
        for (int i = 0; i < tl.size(); ++i) {
            byte value = tl.get(i);
            int color = value & GameConstant.MAHJONG_CODE_COLOR_MASK;
            if (color == cc) {
                if (hun_cd != value) {
                    cs.add(value);
                } else if (hun_cd == value && addHunNum < use_hun_num) {
                    cs.add(value);
                    addHunNum++;
                }
            }
        }
        Collections.sort(cs);
        return cs;
    }

    @Override
    public MahjongCheckResult check_peng(GameTable gt, byte card, Player pl) {
        if (pl.isWin()) {
            return null;
        }


        byte pizi = gt.getRiffraffCard();
        byte laizi = gt.getLazarailloCard();

        // 痞子、癞子不能碰
        //痞子在杠里判断
        if (card == pizi || card == laizi) {
            return null;
        }

        if (pl.getLastCancelPengCard() == card) {
            logger.info(pl.getPlayerIndex() + ",取消过碰,不能再碰这张牌了,tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
            return null;
        }

        int cd = card & 0xff;
        MahjongCheckResult result = null;
        int same_card_num = pl.getXCardNumInHand(card);
        if (same_card_num >= 2) {
            result = new MahjongCheckResult();
            result.targetCard = card;
            result.pengCardValue = cd | (cd << 8);
            result.playerTableIndex = pl.getTablePos();
            result.opertaion = GameConstant.MAHJONG_OPERTAION_PENG;
        }
        return result;
    }

    /**
     * 潜江麻将不能吃
     *
     * @param gt
     * @param card
     * @param pl
     * @return
     */
    @Override
    public MahjongCheckResult check_chi(GameTable gt, byte card, Player pl) {
        return null;
    }


    @Override
    public void goldCalculateHu(GameTable gt, List<Player> huPlayers, Player pao_pl) {
        logger.info("开始计算胡牌分数tableId:"+gt.getVipTableID()+",圈数:"+gt.getHandNum());
        if (pao_pl != null && huPlayers != null) {
            for (Player huPlayer : huPlayers) {
                if (pao_pl.getPlayerID().equals(huPlayer.getPlayerID())) {
                    logger.error("win_lose_gold_calculate_hu, error");
                    return;
                }
            }
        }

        byte laizi = gt.getLazarailloCard();
        int dizhu = gt.getBaseGold();
        byte pizi = gt.getRiffraffCard();
        //记录每个玩家癞子杠的倍数
        List<Player> plist = gt.getPlayers();
        for (Player player : plist) {
            player.setHuDesc("");
            player.setWinLoseGoldNum(0);
            int laiziNum = 0;
            List<CardDown> allCardDown = player.getCardsDown();
            for (CardDown cardDown : allCardDown) {
                if (((byte) cardDown.cardValue)==laizi) {
                    laiziNum++;
                }
            }
            int laiziFan = calLaiziFan(laiziNum);
            if (laiziFan > 1) {
                player.setHuDesc("癞子杠*"+laiziFan+":");
                logger.info(player.getPlayerIndex()+":玩家癞子杠次数"+laiziNum+",癞子杠翻数:"+laiziFan+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
            }
            player.setBao2Score(laiziFan);
        }

        //默认笑的倍数
        int xiaojiabei = 1;
        if ((GameRule.GAME_PLAY_RULE_QIANJIANG_XIAOJIABEI & gt.getVipRule()) != 0) {
            xiaojiabei = 2;
        }

        //胡牌
        if(huPlayers!=null) {
            for (Player huPlayer : huPlayers) {
                boolean yinghu = true;
                boolean chaoTianHu = false;
                if((huPlayer.getHuFanResult()&GameRule.MAHJONG_HU_CODE_YOU_LAI_ZI)!=0){
                    yinghu = false;//癞子归位、无癞子、做将不算归位
                }
                //判断是否朝天胡
                if ((gt.getVipRule() & GameRule.GAME_PLAY_RULE_QIANJIANG_YILAIDAODI) != 0 &&
                        (gt.getVipRule() & GameRule.GAME_PLAY_RULE_QIANJIANG_CHAOTIANHU) != 0 && huPlayer.getHuCard() == pizi) {
                    if (huPlayer.getXCardNumInHand(pizi) >= 2) {
                        chaoTianHu = true;
                    }
                }
                String hu_str = "胡";
                int hu_fan = 0;
                if (pao_pl == null) {//是自摸不是点炮
                    huPlayer.setFanType(huPlayer.getFanType() | GameConstant.MAHJONG_HU_CODE_WIN | GameConstant.MAHJONG_HU_CODE_ZI_MO);
                    if (yinghu) {//硬胡自摸
                        hu_fan = 4;
                        hu_str = "黑摸胡牌";
                    } else {
                        hu_fan = 2;
                        hu_str = "自摸胡牌";
                    }
                    logger.info(huPlayer.getPlayerIndex()+":"+hu_str+"翻数:"+hu_fan+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                    //计算自摸
                    int total_hu_win = 0;
                    int chaoTianHu_win = 0;
                    for (Player player : plist) {
                        int hu_lose = 0;
                        int chaoTianHu_lose = 0;
                        if (player.getPlayerID().equals(huPlayer.getPlayerID())) {
                            continue;
                        }
                        //胡牌
                        hu_lose = huPlayer.getBao2Score() * player.getBao2Score() * hu_fan;
                        total_hu_win += hu_lose;
                        player.setWinLoseGoldNum(player.getWinLoseGoldNum() + (0 - hu_lose*dizhu));
                        player.setHuDesc(player.getHuDesc()+hu_str + "-" + hu_lose*dizhu);
                        //朝天胡
                        if (chaoTianHu) {
                            chaoTianHu_lose = huPlayer.getBao2Score() * player.getBao2Score() * 2 * xiaojiabei;
                            chaoTianHu_win += chaoTianHu_lose;
                            player.setWinLoseGoldNum(player.getWinLoseGoldNum() + (0 - chaoTianHu_lose*dizhu));
                            player.setHuDesc(player.getHuDesc() + " 朝天胡-" + chaoTianHu_lose*dizhu);
                        }
                        logger.info(player.getPlayerIndex()+"分数:"+player.getWinLoseGoldNum()+",desc:"+player.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                    }
                    huPlayer.setWinLoseGoldNum(huPlayer.getWinLoseGoldNum() + total_hu_win*dizhu);
                    huPlayer.setHuDesc(huPlayer.getHuDesc()+hu_str+"+" + total_hu_win*dizhu);
                    //朝天胡
                    if (chaoTianHu) {
                        huPlayer.setWinLoseGoldNum(huPlayer.getWinLoseGoldNum() + chaoTianHu_win*dizhu);
                        huPlayer.setHuDesc(huPlayer.getHuDesc()+" 朝天胡+" + chaoTianHu_win*dizhu);
                    }
                } else {//计算点炮胡牌
                    hu_fan=2;
                    if (yinghu) {//硬胡自摸
                        hu_str = "点炮硬胡";
                    }else {
                        hu_str = "点炮胡牌";
                    }
                    huPlayer.setFanType(huPlayer.getFanType() | GameConstant.MAHJONG_HU_CODE_WIN | GameConstant.MAHJONG_HU_CODE_DIAN_PAO);
                    int dianpao_lose = huPlayer.getBao2Score() * pao_pl.getBao2Score() * 2;
                    huPlayer.setWinLoseGoldNum(huPlayer.getWinLoseGoldNum() + dianpao_lose*dizhu);
                    huPlayer.setHuDesc(huPlayer.getHuDesc()+hu_str+"+" + dianpao_lose*dizhu);
                    pao_pl.setWinLoseGoldNum(pao_pl.getWinLoseGoldNum() + (0 - dianpao_lose*dizhu));
                    pao_pl.setHuDesc(pao_pl.getHuDesc()+"放炮-" + dianpao_lose*dizhu);
                    //朝天胡
                    if (chaoTianHu) {
                        int chaoTianHu_lose=huPlayer.getBao2Score() * pao_pl.getBao2Score() * 1 * xiaojiabei;
                        huPlayer.setWinLoseGoldNum(huPlayer.getWinLoseGoldNum() + chaoTianHu_lose*dizhu);
                        huPlayer.setHuDesc(huPlayer.getHuDesc()+" 朝天胡+" + chaoTianHu_lose*dizhu);
                        pao_pl.setWinLoseGoldNum(pao_pl.getWinLoseGoldNum() + (0 - chaoTianHu_lose*dizhu));
                        pao_pl.setHuDesc(pao_pl.getHuDesc()+" 朝天胡-" + chaoTianHu_lose*dizhu);
                    }
                    logger.info(pao_pl.getPlayerIndex()+"分数:"+pao_pl.getWinLoseGoldNum()+",desc:"+pao_pl.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                }
                logger.info(huPlayer.getPlayerIndex()+"分数:"+huPlayer.getWinLoseGoldNum()+",desc:"+huPlayer.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
            }
        }
        //杠上炮
        boolean isGangShangPao = false;
        if(huPlayers!=null && huPlayers.size()>0 && pao_pl!=null && gt.getGangPlayer() != null && gt.getGangPlayer().getPlayerID().equals(pao_pl.getPlayerID())) {
            isGangShangPao = true;
        }
        //支持四杠癞玩法,计算四杠癞
        if ((gt.getVipRule() & GameRule.GAME_PLAY_RULE_QIANJIANG_YILAIDAODI) != 0
                && (gt.getVipRule() & GameRule.GAME_PLAY_RULE_QIANJIANG_SIGNAGLAI) != 0) {
            logger.info("开始计算四杠癞分数"+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
            for (Player player : plist) {
                int total_silai_win = 0;
                //玩家杠了四个癞子
                if (player.getBao2Score() == 16) {
                    for (Player player_silai : plist) {
                        int silai_lose = 25;//赢25
                        if (player.getPlayerID().equals(player_silai.getPlayerID())) {
                            continue;
                        }
                        total_silai_win += silai_lose;
                        player_silai.setWinLoseGoldNum(player_silai.getWinLoseGoldNum() + (0 - silai_lose*dizhu));
                        player_silai.setHuDesc(player_silai.getHuDesc() + " 四癞杠-" + silai_lose*dizhu);
                        logger.info(player_silai.getPlayerIndex()+"分数:"+player_silai.getWinLoseGoldNum()+",desc:"+player_silai.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                    }
                    player.setWinLoseGoldNum(player.getWinLoseGoldNum() + total_silai_win*dizhu);
                    player.setHuDesc(player.getHuDesc() + " 四癞杠+" + total_silai_win*dizhu);
                    logger.info(player.getPlayerIndex()+"分数:"+player.getWinLoseGoldNum()+",desc:"+player.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                }
            }

        }

        //计算补杠、明杠牌的分数
        logger.info("开始计算杠牌分数"+ ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
        for (Player player : plist) {
            int i=0;
            for (CardDown cd : player.getCardsDown()) {
                i++;
                int size = player.getCardsDown().size();//玩家出牌列表，不含癞子杠
                //杠上炮玩家除癞子外最后一次出牌(杠,痞子碰)，不算赢分
                if(isGangShangPao && player.getPlayerID().equals(pao_pl.getPlayerID()) && i==size){
                    continue;
                }
                if(cd.type == GameConstant.MAHJONG_OPERTAION_BU_GANG){
                    int total_gang_win = 0;
                    for (Player gang_player : plist) {
                        int gang_lose = 0;
                        if (player.getPlayerID().equals(gang_player.getPlayerID())) {
                            continue;
                        }
                        gang_lose = player.getBao2Score() * gang_player.getBao2Score() * 1 * xiaojiabei;
                        total_gang_win += gang_lose;
                        int winLoseGoldNum = gang_player.getWinLoseGoldNum();
                        gang_player.setWinLoseGoldNum(winLoseGoldNum+(0-gang_lose*dizhu));
                        String huDesc = gang_player.getHuDesc();
                        gang_player.setHuDesc(huDesc+" 回头笑-"+gang_lose*dizhu);
                        logger.info(gang_player.getPlayerIndex()+"分数:"+gang_player.getWinLoseGoldNum()+",desc:"+gang_player.getHuDesc()+ ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                    }
                    int winLoseGoldNum = player.getWinLoseGoldNum();
                    player.setWinLoseGoldNum(winLoseGoldNum+total_gang_win*dizhu);
                    player.setHuDesc(player.getHuDesc()+" 回头笑+"+total_gang_win*dizhu);
                    logger.info(player.getPlayerIndex()+"分数:"+player.getWinLoseGoldNum()+",desc:"+player.getHuDesc()+ ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                } else if (cd.type == GameConstant.MAHJONG_OPERTAION_AN_GANG) {
                    int total_gang_win = 0;
                    for (Player gang_player : plist) {
                        int gang_lose = 0;
                        if (player.getPlayerID().equals(gang_player.getPlayerID())) {
                            continue;
                        }
                        gang_lose = player.getBao2Score() * gang_player.getBao2Score() * 2 * xiaojiabei;
                        total_gang_win += gang_lose;
                        int winLoseGoldNum = gang_player.getWinLoseGoldNum();
                        gang_player.setWinLoseGoldNum(winLoseGoldNum+(0-gang_lose*dizhu));
                        String huDesc = gang_player.getHuDesc();
                        gang_player.setHuDesc(huDesc+" 闷笑-"+gang_lose*dizhu);
                        logger.info(gang_player.getPlayerIndex()+"分数:"+gang_player.getWinLoseGoldNum()+",desc:"+gang_player.getHuDesc()+ ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                    }
                    int winLoseGoldNum = player.getWinLoseGoldNum();
                    player.setWinLoseGoldNum(winLoseGoldNum+total_gang_win*dizhu);
                    player.setHuDesc(player.getHuDesc()+" 闷笑+"+total_gang_win*dizhu);
                    logger.info(player.getPlayerIndex()+"分数:"+player.getWinLoseGoldNum()+",desc:"+player.getHuDesc()+ ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                }else if (cd.type == GameConstant.MAHJONG_OPERTAION_MING_GANG || (cd.type == GameConstant.MAHJONG_OPERTAION_PENG && pizi == (byte) cd.cardValue)) {
                    Integer playerIndex = cd.chuPlayer.getPlayerIndex();
                    Player chuPlayer=getPlayerFromGt(gt,playerIndex);
                    int gang_lose = player.getBao2Score() * chuPlayer.getBao2Score() * 1 * xiaojiabei;
                    player.setWinLoseGoldNum(player.getWinLoseGoldNum() + gang_lose*dizhu);
                    player.setHuDesc(player.getHuDesc() + " 点笑+" + gang_lose*dizhu);
                    chuPlayer.setWinLoseGoldNum(chuPlayer.getWinLoseGoldNum() + (0 - gang_lose*dizhu));
                    chuPlayer.setHuDesc(chuPlayer.getHuDesc() + " 点笑-" + gang_lose*dizhu);
                    logger.info(chuPlayer.getPlayerIndex()+"分数:"+chuPlayer.getWinLoseGoldNum()+",desc:"+chuPlayer.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                    logger.info(player.getPlayerIndex()+"分数:"+player.getWinLoseGoldNum()+",desc:"+player.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                }
            }
        }
        //胡了，计算杠上炮
        if(huPlayers!=null) {
            logger.info("开始计算杠上炮"+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
            for (Player huPlayer : huPlayers) {
                if (huPlayer!=null && pao_pl!=null && gt.getGangPlayer() != null && gt.getGangPlayer().getPlayerID().equals(pao_pl.getPlayerID())) {
                    List<CardDown> cardsDown = gt.getGangPlayer().getCardsDown();
                    if(cardsDown.size()<1){
                        break;//开局癞子杠，出牌有人胡的情况
                    }
                    CardDown cd= cardsDown.get(cardsDown.size()-1);//看除了癞子杠外最后一张牌是不是杠
                    int fan_gang = 0;
                    if(cd.type == GameConstant.MAHJONG_OPERTAION_BU_GANG ){
                        logger.info("杠上炮类型:补杠,card:"+Integer.toHexString(cd.cardValue)+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                        fan_gang = 1 * xiaojiabei;
                    }else if(cd.type == GameConstant.MAHJONG_OPERTAION_AN_GANG){
                        logger.info("杠上炮类型:暗杠,card:"+Integer.toHexString(cd.cardValue)+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                        fan_gang = 2 * xiaojiabei;
                    }
                    //杠上炮，杠的人不能收杠的钱,杠应该收得的钱给胡牌的人
                    if(cd.type == GameConstant.MAHJONG_OPERTAION_BU_GANG || cd.type == GameConstant.MAHJONG_OPERTAION_AN_GANG){
                        int total_gangshangpao_win = 0;
                        for (Player gang_player : plist) {
                            int gang_lose = 0;
                            if (gt.getGangPlayer().getPlayerID().equals(gang_player.getPlayerID())) {
                                continue;
                            }
                            //有人点炮，其他玩家不用付杠的分，要把前面的杠的分加上去
                            gang_lose = gt.getGangPlayer().getBao2Score() * gang_player.getBao2Score() * fan_gang;
                            total_gangshangpao_win += gang_lose;
                        }
                        //把点炮的玩家杠的分减去
                        gt.getGangPlayer().setWinLoseGoldNum( gt.getGangPlayer().getWinLoseGoldNum()-total_gangshangpao_win*dizhu);
                        gt.getGangPlayer().setHuDesc( gt.getGangPlayer().getHuDesc()+" 杠上炮-"+total_gangshangpao_win*dizhu);
                        huPlayer.setWinLoseGoldNum(huPlayer.getWinLoseGoldNum()+total_gangshangpao_win*dizhu);
                        huPlayer.setHuDesc(huPlayer.getHuDesc()+" 杠上炮+"+total_gangshangpao_win*dizhu);
                        logger.info(gt.getGangPlayer().getPlayerIndex()+"分数:"+gt.getGangPlayer().getWinLoseGoldNum()+"desc:"+gt.getGangPlayer().getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                        logger.info(huPlayer.getPlayerIndex()+"分数:"+huPlayer.getWinLoseGoldNum()+",desc:"+huPlayer.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                    }
                    if(cd.type == GameConstant.MAHJONG_OPERTAION_MING_GANG || (cd.type == GameConstant.MAHJONG_OPERTAION_PENG && pizi == (byte)cd.cardValue)){
                        logger.info("杠上炮类型:明杠,card:"+Integer.toHexString(cd.cardValue)+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                        Integer playerIndex = cd.chuPlayer.getPlayerIndex();
                        Player chuPlayer=getPlayerFromGt(gt,playerIndex);
                        int gangshangpao_lose =  gt.getGangPlayer().getBao2Score() * chuPlayer.getBao2Score() * 1 * xiaojiabei;
                        gt.getGangPlayer().setWinLoseGoldNum(gt.getGangPlayer().getWinLoseGoldNum()-gangshangpao_lose*dizhu);
                        gt.getGangPlayer().setHuDesc(gt.getGangPlayer().getHuDesc()+" 杠上炮-"+gangshangpao_lose*dizhu);
                        huPlayer.setWinLoseGoldNum(huPlayer.getWinLoseGoldNum()+gangshangpao_lose*dizhu);
                        huPlayer.setHuDesc(huPlayer.getHuDesc()+" 杠上炮+"+gangshangpao_lose*dizhu);
                        logger.info(gt.getGangPlayer().getPlayerIndex()+"分数:"+gt.getGangPlayer().getWinLoseGoldNum()+"desc:"+gt.getGangPlayer().getHuDesc()+ ",tableID=" + gt.getTableID()+ ",handNum=" + gt.getHandNum());
                        logger.info(huPlayer.getPlayerIndex()+"分数:"+huPlayer.getWinLoseGoldNum()+",desc:"+huPlayer.getHuDesc()+ ",tableID=" + gt.getVipTableID()+ ",handNum=" + gt.getHandNum());
                    }
                    //其他情况不算杠上炮
                }
            }
        }
        for (Player player : plist) {
            player.setBao2Score(0);
        }
    }

    @Override
    public void goldCalculateLiuju(GameTable gt) {
        logger.info("开始计算流局分数" + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
        byte laizi = gt.getLazarailloCard();
        byte pizi = gt.getRiffraffCard();
        int dizhu = gt.getBaseGold();
        //记录每个玩家癞子杠的倍数
        List<Player> plist = gt.getPlayers();
        for (Player player : plist) {
            player.setHuDesc("");
            player.setWinLoseGoldNum(0);
            int laiziNum = 0;
            List<CardDown> allCardDown = player.getCardsDown();
            for (CardDown cardDown : allCardDown) {
                if (((byte) cardDown.cardValue) == laizi) {
                    laiziNum++;
                }
            }
            int laiziFan = calLaiziFan(laiziNum);
            if (laiziFan > 1) {
                player.setHuDesc("癞子杠*" + laiziFan + ":");
                logger.info(player.getPlayerIndex() + ":玩家癞子杠次数" + laiziNum + ",癞子杠翻数:" + laiziFan + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
            }
            player.setBao2Score(laiziFan);
        }
        //支持四杠癞玩法,计算四杠癞
        if ((gt.getVipRule() & GameRule.GAME_PLAY_RULE_QIANJIANG_YILAIDAODI) != 0
                && (gt.getVipRule() & GameRule.GAME_PLAY_RULE_QIANJIANG_SIGNAGLAI) != 0) {
            logger.info("开始计算四杠癞分数" + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
            for (Player player : plist) {
                int total_silai_win = 0;
                //玩家杠了四个癞子
                if (player.getBao2Score() == 16) {
                    for (Player player_silai : plist) {
                        int silai_lose = 25;//赢25
                        if (player.getPlayerID().equals(player_silai.getPlayerID())) {
                            continue;
                        }
                        total_silai_win += silai_lose;
                        player_silai.setWinLoseGoldNum(player_silai.getWinLoseGoldNum() + (0 - silai_lose * dizhu));
                        player_silai.setHuDesc(player_silai.getHuDesc() + " 四癞杠-" + silai_lose * dizhu);
                        logger.info(player_silai.getPlayerIndex() + "分数:" + player_silai.getWinLoseGoldNum() +
                                ",desc:" + player_silai.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                    }
                    player.setWinLoseGoldNum(player.getWinLoseGoldNum() + total_silai_win * dizhu);
                    player.setHuDesc(player.getHuDesc() + " 四癞杠+" + total_silai_win * dizhu);
                    logger.info(player.getPlayerIndex() + "分数:" + player.getWinLoseGoldNum() + ",desc:" + player.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                }
            }

        }
        //默认笑的倍数
        int xiaojiabei = 1;
        if ((GameRule.GAME_PLAY_RULE_QIANJIANG_XIAOJIABEI & gt.getVipRule()) != 0) {
            xiaojiabei = 2;
        }
        //计算补杠、明杠牌的分数
        for (Player player : plist) {
            for (CardDown cd : player.getCardsDown()) {
                if (cd.type == GameConstant.MAHJONG_OPERTAION_BU_GANG) {
                    int total_gang_win = 0;
                    for (Player gang_player : plist) {
                        int gang_lose = 0;
                        if (player.getPlayerID().equals(gang_player.getPlayerID())) {
                            continue;
                        }
                        gang_lose = player.getBao2Score() * gang_player.getBao2Score() * 1 * xiaojiabei;
                        total_gang_win += gang_lose;
                        int winLoseGoldNum = gang_player.getWinLoseGoldNum();
                        gang_player.setWinLoseGoldNum(winLoseGoldNum + (0 - gang_lose * dizhu));
                        String huDesc = gang_player.getHuDesc();
                        gang_player.setHuDesc(huDesc + " 回头笑-" + gang_lose * dizhu);
                        logger.info(gang_player.getPlayerIndex() + "分数:" + gang_player.getWinLoseGoldNum() + ",desc:"
                                + gang_player.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());

                    }
                    int winLoseGoldNum = player.getWinLoseGoldNum();
                    player.setWinLoseGoldNum(winLoseGoldNum + total_gang_win * dizhu);
                    player.setHuDesc(player.getHuDesc() + " 回头笑+" + total_gang_win * dizhu);
                    logger.info(player.getPlayerIndex() + "分数:" + player.getWinLoseGoldNum() + ",desc:"
                            + player.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                } else if (cd.type == GameConstant.MAHJONG_OPERTAION_AN_GANG) {
                    int total_gang_win = 0;
                    for (Player gang_player : plist) {
                        int gang_lose = 0;
                        if (player.getPlayerID().equals(gang_player.getPlayerID())) {
                            continue;
                        }
                        gang_lose = player.getBao2Score() * gang_player.getBao2Score() * 2 * xiaojiabei;
                        total_gang_win += gang_lose;
                        int winLoseGoldNum = gang_player.getWinLoseGoldNum();
                        gang_player.setWinLoseGoldNum(winLoseGoldNum + (0 - gang_lose * dizhu));
                        String huDesc = gang_player.getHuDesc();
                        gang_player.setHuDesc(huDesc + " 闷笑-" + gang_lose * dizhu);
                        logger.info(gang_player.getPlayerIndex() + "分数:" + gang_player.getWinLoseGoldNum() + ",desc:"
                                + gang_player.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                    }
                    int winLoseGoldNum = player.getWinLoseGoldNum();
                    player.setWinLoseGoldNum(winLoseGoldNum + total_gang_win * dizhu);
                    player.setHuDesc(player.getHuDesc() + " 闷笑+" + total_gang_win * dizhu);
                    logger.info(player.getPlayerIndex() + "分数:" + player.getWinLoseGoldNum() + ",desc:"
                            + player.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                } else if (cd.type == GameConstant.MAHJONG_OPERTAION_MING_GANG || (cd.type == GameConstant.MAHJONG_OPERTAION_PENG && pizi == (byte) cd.cardValue)) {
                    Integer playerIndex = cd.chuPlayer.getPlayerIndex();
                    Player chuPlayer = getPlayerFromGt(gt, playerIndex);
                    int gang_lose = player.getBao2Score() * chuPlayer.getBao2Score() * 1 * xiaojiabei;
                    player.setWinLoseGoldNum(player.getWinLoseGoldNum() + gang_lose * dizhu);
                    player.setHuDesc(player.getHuDesc() + " 点笑+" + gang_lose * dizhu);
                    chuPlayer.setWinLoseGoldNum(chuPlayer.getWinLoseGoldNum() + (0 - gang_lose * dizhu));
                    chuPlayer.setHuDesc(chuPlayer.getHuDesc() + " 点笑-" + gang_lose * dizhu);
                    logger.info(chuPlayer.getPlayerIndex() + "分数:" + chuPlayer.getWinLoseGoldNum() + ",desc:" + chuPlayer.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                    logger.info(player.getPlayerIndex() + "分数:" + player.getWinLoseGoldNum() + ",desc:" + player.getHuDesc() + ",tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
                }
            }
        }
        for (Player player : plist) {
            player.setBao2Score(0);
        }
    }

    private int calLaiziFan(int laiziNum) {
        int laizifan = 1;
        for (int i = 0; i < laiziNum; i++) {
            laizifan = laizifan * 2;
        }
        return laizifan;
    }

    private Player getPlayerFromGt(GameTable gt, Integer playerIndex) {
        for (Player player : gt.getPlayers()) {
            if (player.getPlayerIndex().intValue() == playerIndex.intValue()) {
                return player;
            }
        }
        logger.error(playerIndex + "不在GameTable.getPlayers()中,tableID=" + gt.getVipTableID() + ",handNum=" + gt.getHandNum());
        return null;
    }
}
